package org.zjx.route.entity;

import lombok.Data;

import java.util.Objects;

/**
 * 游戏内位置坐标实体类
 * 表示游戏中的一个具体位置，包含场景、房间和坐标信息
 */
@Data
public class Location {
    private String sceneName; // 场景名称(必填)
    private String roomName;  // 房间名称(可为空)
    private int x;            // X坐标
    private int y;            // Y坐标

    /**
     * 构造函数(无房间名)
     * @param sceneName 场景名称
     * @param x X坐标
     * @param y Y坐标
     */
    public Location(String sceneName, int x, int y) {
        this(sceneName, null, x, y);
    }

    /**
     * 完整构造函数
     * @param sceneName 场景名称
     * @param roomName 房间名称
     * @param x X坐标
     * @param y Y坐标
     * @throws IllegalArgumentException 如果场景名称为空
     */
    public Location(String sceneName, String roomName, int x, int y) {
        if (sceneName == null || sceneName.isBlank()) {
            throw new IllegalArgumentException("Scene name cannot be empty");
        }
        this.sceneName = sceneName;
        this.roomName = roomName;
        this.x = x;
        this.y = y;
    }

    /**
     * 判断是否同场景
     * @param other 另一个位置
     * @return 如果场景相同返回true
     */
    public boolean sameScene(Location other) {
        return this.sceneName.equals(other.sceneName);
    }

    /**
     * 判断是否同房间
     * @param other 另一个位置
     * @return 如果场景和房间都相同返回true
     */
    public boolean sameRoom(Location other) {
        if (this.roomName == null || other.roomName == null) {
            return false;
        }
        return sameScene(other) && this.roomName.equals(other.roomName);
    }

    /**
     * 判断是否同场景且距离过近
     * @param other 另一个位置
     * @return 如果场景相同且过近返回true
     */
    /**
     * 判断是否邻近（同场景且距离<=10像素）
     */
    public boolean isNear(Location other) {
        return sameScene(other) && distanceTo(other) <= 10.0;
    }

    /**
     * 计算同场景内的距离
     * @param other 另一个位置
     * @return 两点之间的距离(像素单位)
     * @throws IllegalArgumentException 如果不在同一场景
     */
    public double distanceTo(Location other) {
        if (!sameScene(other)) {
            throw new IllegalArgumentException("Cannot calculate distance between different scenes");
        }
        int dx = this.x - other.x;
        int dy = this.y - other.y;
        return Math.sqrt(dx * dx + dy * dy);
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Location location = (Location) o;
        return x == location.x &&
                y == location.y &&
                sceneName.equals(location.sceneName) &&
                Objects.equals(roomName, location.roomName);
    }

    @Override
    public int hashCode() {
        return Objects.hash(sceneName, roomName, x, y);
    }

    /**
     * 转换为字符串表示
     * @return 格式化的位置字符串
     */
    @Override
    public String toString() {
        return roomName != null ?
                String.format("%s(%s)[%d,%d]", sceneName, roomName, x, y) :
                String.format("%s[%d,%d]", sceneName, x, y);
    }
}